<?php

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

require_once __DIR__ . '/../vendor/autoload.php';

// load env
$dotenv = \Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();

header('Access-Control-Allow-Origin: ' . getenv('FRONTEND_URL'));
header('Access-Control-Allow-Credentials: true');
header("Access-Control-Allow-Headers: *, Content-Type");
header("Access-Control-Max-Age: 60");

if($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    die();
}

if($_SERVER['REQUEST_METHOD'] !== 'POST'){
    http_response_code(405);
    die('405 Method Not Allowed');
}

header("Content-Type: application/json");


$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
    //$r->addGroup('/product', function(FastRoute\RouteCollector $r){ \App\ProductController::register($r); });
    $r->post('/', [\App\PublicAPI\MainController::class, 'test']);
    $r->post('/version', [\App\PublicAPI\MainController::class, 'version']);
    $r->post('/login', [\App\PublicAPI\AuthController::class, 'login']);
    $r->post('/checkUsername', [\App\PublicAPI\AuthController::class, 'checkUsername']);
    $r->post('/register', [\App\PublicAPI\AuthController::class, 'register']);
    $r->post('/asset', [\App\PublicAPI\MainController::class, 'asset']);

    $r->addGroup('/captcha', function(FastRoute\RouteCollector $r){ \App\PublicAPI\CaptchaController::register($r); });
    $r->addGroup('/room', function(FastRoute\RouteCollector $r){ \App\PublicAPI\RoomController::register($r); });
    $r->addGroup('/storage', function(FastRoute\RouteCollector $r){ \App\PublicAPI\StorageController::register($r); });

    $r->post('/alive', [\App\PublicAPI\UserController::class, 'alive']);
    $r->post('/online', [\App\PublicAPI\UserController::class, 'online']);
    $r->post('/user/current', [\App\PublicAPI\UserController::class, 'current']);
    $r->post('/user/balance', [\App\PublicAPI\UserController::class, 'balance']);
});

// Fetch method and URI from somewhere
$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];

// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
    $uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);

function output($out = true, $success = true) {
    if(is_bool($out)) {
        if($out === true) die('{"status":0}');
        if($out === false) die('{"status":1}');
    }
    if(is_null($out)) die('{"status":0}');
    if(is_string($out)) {
        die(json_encode(['status' => ($success === true ? 0 : 1), 'message' => $out]));
    }
    if(is_array($out)) {
        die(json_encode(['status' => ($success === true ? 0 : 1), 'data' => $out]));
    }
    die('{"status":1,"message":"Unknown output! "}');
}

$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        // ... 404 Not Found
        http_response_code(404);
        die('404 Not Found');
        break;
    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        $allowedMethods = $routeInfo[1];
        // ... 405 Method Not Allowed
        http_response_code(405);
        die('405 Method Not Allowed');
        break;
    case FastRoute\Dispatcher::FOUND:
        $instance = null;
        try {
            $handler = $routeInfo[1];
            $instance = new $handler[0];

            // check for input
            $params = null;
            if ($httpMethod === 'POST') { // should always be post
                $in = file_get_contents('php://input');
                $params = json_decode($in, true);
                if ($params === null) die('{"status":1,"message":"Invalid input! "}');
                // $j = json_decode($in, true);
                // if($j === null or !isset($j['d']) or !isset($j['t']) or !isset($j['s'])) {
                //     die('{"status":1,"message":"Invalid input! "}');
                // }
                // $timestamp = intval($j['t']);
                // if(abs(time() - $timestamp) > 5) {
                //     die('{"status":1,"message":"Query expired! "}');
                // }
                // $correct = sha1('sig:' . $j['d'] . ':' . $timestamp . ':' . getenv('API_KEY'));
                // if($j['s'] !== $correct) {
                //     die('{"status":1,"message":"Invalid signature! "}');
                // }
                // $params = json_decode($j['d'], true);
            }

            if($instance->needAuth !== false) {
                // validate
                if (!isset($params['token']) or !\App\Tools\Pattern::matches('/[A-Za-z0-9\+\/=]+:[A-Za-z0-9\+\/=]+/', $params['token'])) {
                    output('not authorized', false);
                    return;
                }
                $token = \App\Tools\Encryption::decrypt_token($params['token']);
                $instance->user = $token;
                if ($token === null) {
                    output('session expired', false);
                    return;
                }
            }

            $ret = call_user_func_array([$instance, $handler[1]], [$params]);
            if (is_bool($ret)) output($ret);
            if (is_array($ret)) output($ret[0], $ret[1]);
            output($ret);
        } catch (\Exception $ex) {
            if($instance !== null and $instance->getPDO()->inTransaction()) {
                $instance->getPDO()->rollback();
                trigger_error('Error Message: ' . $ex->getMessage() . "\n" . print_r($ex->getTrace(), true));
                trigger_error('Transaction rolled back! ');
            }
            // trigger_error($ex);
            output(empty($ex->getMessage()) ? 'server error' : $ex->getMessage(), false);
        }
        break;
}
